package com.aegean.MonitorExamSYS.center.action;

import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.apache.struts2.interceptor.ServletRequestAware;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;

import com.aegean.MonitorExamSYS.center.component.SelectConductionInfo;
import com.opensymphony.xwork2.ActionSupport;
import edu.emory.mathcs.backport.java.util.Collections;

@Controller("AutoArrangeForConduction")
@Scope("prototype")
public class AutoArrangeForConduction extends ActionSupport implements
		ServletRequestAware {
	private static final long serialVersionUID = 9041692324498918694L;
	private static int limit = 20;// 限制每个考场至少的人数
	private LinkedList<SelectConductionInfo> conductions;
	private HttpServletRequest request;
	private HttpSession session;
	private int personCount;
	private static int lastIndex;
	private static int leave;
	private int total;
	private Map<Integer, List<Integer>> con_PositionsMap;//Map for PositionArrange

	public int getTotal() {
		return total;
	}

	public void setTotal(int total) {
		this.total = total;
	}

	public static int getLimit() {
		return limit;
	}

	public static void setLimit(int limit) {
		AutoArrangeForConduction.limit = limit;
	}

	public LinkedList<SelectConductionInfo> getConductions() {
		return conductions;
	}

	public void setConductions(LinkedList<SelectConductionInfo> conductions) {
		this.conductions = conductions;
	}

	public int getPersonCount() {
		return personCount;
	}

	public void setPersonCount(int personCount) {
		this.personCount = personCount;
	}

	class SortConfirm implements Comparator<SelectConductionInfo> {
		@Override
		public int compare(SelectConductionInfo o1, SelectConductionInfo o2) {
			// TODO Auto-generated method stub
			int result;
			SelectConductionInfo one = (SelectConductionInfo) o1;
			SelectConductionInfo two = (SelectConductionInfo) o2;
			result = one.getPersonCount() < two.getPersonCount() ? 1 : (one
					.getPersonCount() == two.getPersonCount() ? 0 : -1);
			if (result == 0) {
				result = (one.getIncludeCount() - one.getPersonCount()) < (two
						.getIncludeCount() - two.getPersonCount()) ? 1 : ((one
						.getIncludeCount() - one.getPersonCount()) == (two
						.getIncludeCount() - two.getPersonCount()) ? 0 : -1);
				if (result == 0) {
					result = one.getIncludeCount() < two.getIncludeCount() ? 1
							: (one.getIncludeCount() == two.getIncludeCount() ? 0
									: -1);
					if (result == 0) {
						result = one.getCity().compareTo(two.getCity());
						if (result == 0) {
							result = one.getRegion().compareTo(two.getRegion());
						}
					}
				}
			}
			return result;
		}

	}

	private LinkedList<SelectConductionInfo> confirmLimitKill(
			LinkedList<SelectConductionInfo> collection) {
		int leaf = 0;
		int index = 0;
		Iterator<SelectConductionInfo> iterator = collection.iterator();
		while (iterator.hasNext()) {
			SelectConductionInfo object = iterator.next();
			leaf += object.getPersonCount();
		}
		Iterator<SelectConductionInfo> iterator2 = collection.iterator();
		while (iterator2.hasNext() && leaf != 0) {
			SelectConductionInfo object = iterator2.next();
			object.setPersonCount(0);
			index = collection.indexOf(object);
			int count = object.getIncludeCount() - object.getPersonCount();
			if (leaf > count) {
				object.setPersonCount(object.getIncludeCount());
				leaf = leaf - count;
			} else {
				object.setPersonCount(object.getPersonCount() + leaf);
				leaf = 0;
			}
			collection.set(index, object);
		}
		return new LinkedList<SelectConductionInfo>(collection.subList(0,
				index + 1));

	}

	private LinkedList<SelectConductionInfo> confirmConduction(
			LinkedList<SelectConductionInfo> collection) {
		Iterator<SelectConductionInfo> iterator = collection.iterator();
		while (iterator.hasNext() && leave != 0) {
			SelectConductionInfo object = iterator.next();
			lastIndex = collection.indexOf(object);
			if (object.getPersonCount() > object.getIncludeCount()) {
				object.setPersonCount(object.getIncludeCount());
				collection.set(lastIndex, object);
			} else {
				int count = object.getIncludeCount() - object.getPersonCount();
				if (leave > count) {
					object.setPersonCount(object.getIncludeCount());
					leave = leave - count;
				} else {
					object.setPersonCount(object.getPersonCount() + leave);
					leave = 0;
				}
				collection.set(lastIndex, object);
			}
		}
		return collection;
	}

	private LinkedList<SelectConductionInfo> sortConfirmFunction(
			LinkedList<SelectConductionInfo> collection) {
		List<SelectConductionInfo> resultList;
		int sum = 0;
		int index = -1;
		boolean result = true;//判断是否出现考点没有被报名
		Iterator<SelectConductionInfo> iterator = collection.iterator();
		while (iterator.hasNext() && result) {
			SelectConductionInfo object = iterator.next();
			if (object.getPersonCount() < 1) {//如果出现该考点没有考生报名,跳出本次排序
				index = collection.indexOf(object);//记录出现考场为空的考场序号
				result = false;
				break;
			}
			sum += object.getIncludeCount();
			int i = object.getPersonCount() - object.getIncludeCount();
			if (i > 0) {
				leave += i;
			}
		}
		if (sum >= personCount) {// 如果可容人数>报考人数(排除考点没有被报名)
			if (index == -1) {//如果出现考点没有被报名
				return new LinkedList<SelectConductionInfo>(collection.subList(
						0, collection.size()));
			} else {
				resultList = collection.subList(0, index);
			}
		} else {//如果可容人数<报考人数
			boolean result2 = true;// 判断是否满足可容人数>报考人数
			iterator = collection.listIterator(index);
			while (iterator.hasNext() && result2) {
				SelectConductionInfo object = iterator.next();
				sum += object.getIncludeCount();
				if (sum >= personCount) {
					index = collection.indexOf(object);
					result2 = false;
					break;
				}
			}
			resultList = collection.subList(0, index + 1);
		}
		return new LinkedList<SelectConductionInfo>(resultList);
	}

	@Override
	public String execute() throws Exception {
		// TODO Auto-generated method stub
		session = request.getSession();
		conductions = new LinkedList<SelectConductionInfo>(
				(List) session.getAttribute("ConListForCenter"));
		Collections.sort(conductions, new SortConfirm());
		conductions = sortConfirmFunction(new LinkedList<SelectConductionInfo>(
				conductions));
		conductions = confirmConduction(conductions);
		if (lastIndex < conductions.size() - 1) {
			if (conductions.get(lastIndex + 1).getPersonCount() < limit) {
				LinkedList<SelectConductionInfo> past1 = new LinkedList<SelectConductionInfo>(
						conductions.subList(0, lastIndex));
				LinkedList<SelectConductionInfo> past2 = new LinkedList<SelectConductionInfo>(
						conductions.subList(lastIndex, conductions.size()));
				past2 = confirmLimitKill(past2);
				past1.addAll(past2);
				conductions = past1;
			}
		}
		con_PositionsMap = new HashMap<Integer, List<Integer>>();
		for (SelectConductionInfo one : conductions) {
			con_PositionsMap.put(one.getId(), null);
		}
		
		total = conductions.size();
		session.setAttribute("autoArrangeConductionPersonCount", conductions);
		session.setAttribute("confirmConductionsMap", con_PositionsMap);//存储考点考场的分配
		return SUCCESS;
	}

	@Override
	public void setServletRequest(HttpServletRequest request) {
		this.request = request;
	}
}
